Chapter 2: Exercises

Part 1

  1. 請寫一個函式 localMax.m,可用來算出一個向量的局部最大值(Local Maxima)出現的位置。一個元素若比它左右相鄰元素都大,就是一個局部最大值。(若是此元素在起頭或結束的位置,那麼它只要比它的一個相鄰元素大,就是局部最大值。)此函式的輸出入格式如下:
    maxIndex = localMax(vector)
    其中輸出變數 maxIndex 是一個 0-1 的向量,其大小和輸入向量 vector 相同。若 vector(i) 是一個局部最大值,則 maxIndex(i) 為 0,否則為 1。如果你的程式碼是完全向量化的(Fully vectorized),將有加分。
  2. (*) Function for zero crossing rate: 請寫一個函式 zcRate.m,可用來算出一個向量的過零率(Zero crossing rate),定義為相鄰元素穿越零點的個數,其輸出入格式如下:
    count = zcRate(vec)
    其中輸出變數 count 代表向量 vec 中,相鄰元素穿越零點的個數,此即為相鄰元素異號的個數。(你可以假設 vec 的所有元素均不為零。)

    English version:
    Write a function zcRate.m which can compute the zero crossing rate of a vector, defined as the number of zero crossing between neighboring elements:

    count = zcRate(vec)
    The function returns the number of zero crossing in vec, which is also equal to the count of pairs of neighboring elements with different signs. (You can simply assume there no 0 in vec.)

    Test cases:

    • vec = [1 2 -3 4 -2 -4] ==> count = 3
    • vec = [8 3 -13 -4 -1 7 -5 8 -7 -10 10 -2 17 3] ==> count = 8
  3. 寫一個 MATLAB 函式 vecFind.m,其輸出入格式如下:
    index = vecFind(x, y)
    其中 x 和 y 都是向量,index(i) 是 y(i) 出現於向量 x 的位置。例如,當 x = [6 2 4 1] 且 y = [4 6] 時,vecfind 傳回的值是 [3 1],分別代表 4(y(1) 的值)和 6(y(2) 的值)在向量 x 的位置。(為簡化題目起見,我們假設向量 y 的每一個元素一定會出現在向量 x 裡,而且最多只出現一次。)如果你的程式碼是完全向量化的(Fully vectorized),將有加分。

    Hint
    你的程式碼將會用到 find 指令。

  4. 寫一個 MATLAB 函式 cutShort.m,其功能為將「個數小於4、連續的非 nan元素」改為 nan。例如,當輸入為下列向量時:
    [nan 5 3 5 6 3 nan nan 3 4 5 nan 2 nan nan 1 2 3 6]
    cutshort.m傳回的向量為
    [nan 5 3 5 6 3 nan nan nan nan nan nan nan nan nan 1 2 3 6]
    其中 [3 4 5] 和 [2] 被代換成 [nan nan nan] 及 [nan],因為它們都是「個數小於4、連續的非 nan元素」。如果你的程式碼是完全向量化的(Fully vectorized),將有加分。
  5. (**) Function for inverse sorting: 當 a = [92, 95, 58, 75, 69, 82],以下 MATLAB 指令 "[b, index] = sort(a)" 會得到 b = [58, 69, 75, 82, 92, 95] 及 index = [3, 5, 4, 6, 1, 2],其中 index 的每個元素代表 b 的每個元素在 a 的位置,滿足 b 等於 a(index)。請寫一個函數 sortInverseIndex.m,用法如下:
    [b, index2] = sortInverseIndex(a);
    當輸入為 a 時,可傳回排序後的向量 b,並傳回 index2,滿足 a 等於 b(index2)。以上述 a 向量為例,傳回的 index2 應該是 [5, 6, 1, 3, 2, 4]。

    English version:
    When a = [92, 95, 58, 75, 69, 82], MATLAB command "[b, index] = sort(a)" will return b = [58, 69, 75, 82, 92, 95] and index = [3, 5, 4, 6, 1, 2], where each element of index indicates the position of each element of b in a, satisfying b is equal to a(index). Write a function sortInverseIndex.m with the usage:

    [b, index2] = sortInverseIndex(a);
    When the input is a, the function can return the sorted vector b as well as the vector index2 satisfying a is equal to b(index2).

    Test cases

    • a = [92 95 58 75 69 82] ==> b = [58 69 75 82 92 95], index2=[5 6 1 3 2 4]
    • a = [86 3 89 81 39 66 34 22 85 9 90 67 18 61 99 33 45 50 5 55] ==> b = [3 5 9 18 22 33 34 39 45 50 55 61 66 67 81 85 86 89 90 99], index2 = [17 1 18 15 8 13 7 5 16 3 19 14 4 12 20 6 9 10 2 11]

    Hint
    你可以使用迴圈(如 for-loop 和 while-loop 等)完成此作業,但是程式碼會比較凌亂,執行效率也會變差。所以請盡量利用 sort 指令,而不要用到迴圈。
    You can use for-loop or while-loop to accomplish this exercise, but the efficiency will be poor. If possible, please use the built-in command of "sort" as much as possible.

  6. (**) Function for score ranking: 假設在期中考後,我們用一個向量 x 來儲存每個人的考試成績。請寫一個函數 scoreRank.m,輸入為成績向量 x,輸出則是此成績的排名。例如,當 x = [92, 95, 58, 75, 69, 82] 時,scoreRank(x) 回傳的排名向量則是 [2, 1, 6, 4, 5, 3],代表 92 分是排名第 2,95 分是排名第 1,58 分是排名第 6,等等。(你可以假設向量的元素值不會重複。)

    English version:
    We can use a vector to store the scores of midterm exam. Please write a function scoreRank.m that takes the score vector and return the ranking. For instance, if x = [92, 95, 58, 75, 69, 82], the vector returned by scoreRank(x) should be [2, 1, 6, 4, 5, 3], indicating 92 is ranked second, 95 is ranked first, etc. (You can safely assume the elements in the vector are unique.)

    Here is a script for testing your function:

    Example 1: 02-程式碼與記憶體之最佳化/scoreRank01.mx=[92, 95, 58, 75, 69, 82]; out=scoreRank(x); fprintf('x=%s\n', mat2str(x)); fprintf('ranking(x)=%s\n', mat2str(out)); x=rand(1, 10); out=scoreRank(x); fprintf('x=%s\n', mat2str(x)); fprintf('ranking(x)=%s\n', mat2str(out)); x=[92 95 58 75 69 82] ranking(x)=[2 1 6 4 5 3] x=[0.715218175457675 0.812223893127483 0.915191163815951 0.731081459830828 0.836036703073424 0.830886324732234 0.676517083486604 0.985540844495613 0.0699923233988914 0.944075119392345] ranking(x)=[8 6 3 7 4 5 9 1 10 2]

  7. 寫一個 MATLAB 函式 maxCount.m,其輸出入格式如下:
    out = maxCount(vector, element)
    其中 vector 是一個向量,element 是一個純量,out 則是 element 連續出現於向量 vector 中的最大次數。例如,當 vector = [1 2 2 3 3 4 2 2 2 3 2 2 2 2 2 3 1 2] 且 element = 2 時,maxcount 傳回的值是 5,代表 2 在 vector 裡連續出現的最大個數為 5。如果你的程式碼是完全向量化的(Fully vectorized),將有加分。
  8. 一個 d 維的高斯機率密度函數(Gaussian probability density function)可以表示成:
    g(x, m, S) = [(2p)d*|S|]-0.5*exp[-(x-m)TS-1(x-m)/2]
    其中 m 是此高斯機率密度函數的平均向量(Mean vector),S 則是其共變異矩陣(Covariance matrix)。試寫一個函式 gaussian.m,其輸出入格式如下:
    out = gaussian(x, gParam)
    其中 gParam.mu 是此高斯機率密度函數的平均向量,gParam.sigma 是其共變異矩陣,x 則是一個輸入矩陣,其每一列代表此高斯機率密度函數的輸入向量,而 out 則是一個向量,out(i) 代表輸入向量 x(i, :) 在此高斯機率密度函數的值。如果你的程式碼是完全向量化的(Fully vectorized),將有加分。
  9. 請寫一個函式 elementCount.m,可用來算出一個向量中,不同的元素各有幾個,其輸出入格式如下:
    [sorted, count] = elementCount(vector)
    其中 sorted 是在 vector 中,所有不同元素經排序後所得的向量,count(i) 則是 sorted(i) 在 vector 中出現的個數。如果你的程式碼是完全向量化的(Fully vectorized),將有加分。

Part 2

  1. 請寫一個函式,可用來算出一個向量的移動平均值(Running Average),並可指定移動視窗(Moving Window)的長短,此函式的輸出入格式如下:
    output = meanFilter(x, n)
    其中輸入變數 x 是一個向量,n 則是移動視窗的長短,必須是奇數。例如,如果 x = [1 3 2 1 5 0 1],則 output = medianFilter(x, 3) 產生的結果是 [1 2 2 2 1 1 1],換句話說,output(i)=mean(x(i-1:i+1))。(注意:若無法取得完整的視窗,則 output(i)=x(i)。)。如果你的程式碼是完全向量化的(Fully vectorized),將有加分。
  2. 請重複上題,但將平均值的計算改成中位數。

MATLAB程式設計:進階篇